home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr49 / obj2asm.zip / OUTARGET.C < prev    next >
Text File  |  1991-10-02  |  21KB  |  625 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include "o.h"
  5.  
  6. /*
  7. ** Local Prototypes
  8. */
  9. char *seg_name( int, word * );
  10. char *grp_name( int );
  11. void get_seg( char *, FIX_T *, int, void *, int );
  12. void assume( int, int, int );
  13.  
  14. FIXER_T fix_type[] = {
  15.     1, "db",     "low ",      /* LOBYTE  */
  16.     2, "dw",  "offset ",      /* OFFSET  */
  17.     2, "dw",     "seg ",      /* BASE    */
  18.     4, "dd",     "ptr ",      /* POINTER */
  19.     1, "db",    "high ",      /* HIBYTE  */
  20.     2, "dw",  "offset "  };   /* Loader-resolved */
  21.                               /*     OFFSET      */
  22.  
  23. char *seg_name( index, size )
  24.     int             index;
  25.     word    *size;
  26. {
  27.     SEG_T   *segment_rec;
  28.     NAME_T  *name_rec;
  29.  
  30.     seg_search.index = index;
  31.     segment_rec = (SEG_T *)find( (char *)&seg_search, segment_tree, 
  32.                                                         TC seg_compare, NULL );
  33.     if ( segment_rec == NULL ) fmt_error( "Undefinded segment" );
  34.     *size = segment_rec->length;
  35.     name_search.index = segment_rec->name;
  36.     name_rec = (NAME_T *)find( (char *)&name_search, name_tree, 
  37.                                                         TC name_compare, NULL );
  38.     if ( name_rec == NULL ) fmt_error( "Undefined segment name" );
  39.     return( name_rec->name );
  40. }
  41.  
  42. char *grp_name( index )
  43.     int     index;
  44. {
  45.     GRP_T   *grp_rec;
  46.     NAME_T  *name_rec;
  47.  
  48.     grp_search.index = index;
  49.     grp_rec = (GRP_T *)find( (char *)&grp_search, group_tree, 
  50.                                                         TC grp_compare, NULL );
  51.     if ( grp_rec == NULL ) fmt_error( "Undefined group" );
  52.     name_search.index = grp_rec->name;
  53.     name_rec = (NAME_T *)find( (char *)&name_search, name_tree, 
  54.                                                         TC name_compare, NULL );
  55.     if ( name_rec == NULL ) fmt_error( "Undefined group name" );
  56.     return( name_rec->name );
  57. }
  58.  
  59. char *mode_name( mode, index )
  60.     int             mode;
  61.     int             index;
  62. {
  63.     word    dummy;
  64.  
  65.     if ( index == 0 ) {
  66.         return( "NOTHING" );
  67.     }
  68.  
  69.     switch( mode ) {
  70.         case SEGMENT:   return( seg_name(index,&dummy) );
  71.         case GROUP:     return( grp_name(index) );
  72.         case LOCATION:  return( cseg_name );
  73.  
  74.         case EXTERNAL:
  75.         case FRAME:
  76.         case TARGET:
  77.         case NONE:      return( NULL );
  78.     }
  79.     return(NULL);
  80. }
  81.  
  82. void assume( seg_reg, data_mode, data_index )
  83.     int             seg_reg;
  84.     int             data_mode;
  85.     int             data_index;
  86. {
  87.     char            *seg_name;
  88.     extern  char    *sregsc[];
  89.     char            operand[100];
  90.  
  91.     seg_name = mode_name( data_mode, data_index );
  92.     if (seg_name && compatibility != 2 && pass == 3 ) {
  93.         out_opcode( "assume" );
  94.         sprintf( operand, "%s %s", sregsc[seg_reg], seg_name );
  95.         out_operand( operand );
  96.         out_endline();
  97.     }
  98. }
  99.  
  100. void adjust_assumes()
  101. {
  102.     int     seg_reg;
  103.     int     new_mode;
  104.     int     new_index;
  105.  
  106.     for ( seg_reg = 0; seg_reg < MAX_SEG_REGS; seg_reg++ ) {
  107.         new_mode  = seg_rec->new_mode [seg_reg];
  108.         new_index = seg_rec->new_index[seg_reg];
  109.         if ( new_mode  != seg_rec->prv_mode [seg_reg] ||
  110.              new_index != seg_rec->prv_index[seg_reg] ) {
  111.             assume( seg_reg, new_mode, new_index );
  112.             seg_rec->prv_mode [seg_reg] = new_mode;
  113.             seg_rec->prv_index[seg_reg] = new_index;
  114.         }
  115.     }
  116. }
  117.  
  118. void abort_assumes()
  119. {
  120.     int     seg_reg;
  121.  
  122.     for ( seg_reg = 0; seg_reg < MAX_SEG_REGS; seg_reg++ ) {
  123.         seg_rec->new_mode [seg_reg] = seg_rec->prv_mode [seg_reg];
  124.         seg_rec->new_index[seg_reg] = seg_rec->prv_index[seg_reg];
  125.     }
  126. }
  127.  
  128. void get_seg( result, fixup, ref_mode, data, seg_reg )
  129.     char    *result;
  130.     FIX_T   *fixup;
  131.     int     ref_mode;
  132.     void    *data;
  133.     int     seg_reg;
  134. {
  135.     char    *this_name;
  136.     int     form;
  137.     int     mode;
  138.     int     index;
  139.     int     ref_seg;
  140.     EXT_T   *ext_rec;
  141.     PUB_T   *pub_rec;
  142.  
  143.     form  = fixup->form;
  144.     mode  = fixup->a_mode;
  145.     index = fixup->a_index;
  146.  
  147.     strcpy( result, "" );
  148.  
  149.     if ( mode == TARGET || mode == NONE ) {
  150.         return;
  151.     }
  152.  
  153.     /*
  154.     ** Check for Externals with implied or lacking segment
  155.     **  This means that the fixup tells that the external was defined in
  156.     **  that segment (for implied, SI:EI). Or that the external was defined
  157.     **  outside any segment (for lacking, EI:EI).
  158.     */
  159.     if ( fixup->b_mode == EXTERNAL ) {
  160.         ext_rec = data;
  161.         if ( mode == EXTERNAL ) {
  162.             /* Must be EI:EI */
  163.             ext_rec->used = -1;         /* Remove from any segments! */
  164.             return;
  165.         }
  166.         if ( mode == SEGMENT ) {
  167.             ext_rec->pos_abs = FALSE;
  168.             if ( ref_mode != 0 ) {
  169.                 /* Must be Segment:EI */
  170.                 if ( pass == 1 && ext_rec->used == 0 ) {
  171.                     sex_insert( index, ext_rec );
  172.                     ext_rec->used = index;
  173.                 }
  174.                 if ( ext_rec->used == index ) {
  175.                     return;
  176.                 }
  177.             }
  178.         }
  179.     } else {
  180.         if ( fixup->b_mode == SEGMENT ) {
  181.             pub_rec = data;
  182.             if ( ref_mode == 2 && (ref_mode == 1 && form == POINTER) ) {
  183.                 if ( pub_rec->seg_idx == index ) {
  184.                     return;
  185.                 }
  186.             }
  187.         }
  188.     }
  189.  
  190.     /*
  191.     ** On first important fixup, assign the "ASSIGN xx:" values
  192.     */
  193.     if ( ref_mode == 0 || (ref_mode == 1 && form != POINTER) ) {
  194.         ref_seg = seg_reg - ES;                 /* Convert to 0,1,2,3,etc */
  195.         seg_rec->new_mode [ref_seg] = mode;
  196.         seg_rec->new_index[ref_seg] = index;
  197.         if ( mode == SEGMENT ) {
  198.             if ( fixup->b_mode == EXTERNAL && ext_rec->used == index ) {
  199.                 return;
  200.             }
  201.         }
  202.         if ( mode == SEGMENT || mode == GROUP ) {
  203.             if ( fixup->b_mode == SEGMENT || fixup->b_mode == EXTERNAL ) {
  204.                 return;
  205.             }
  206.         }
  207.         /*
  208.         ** Frame on a code reference is always taken from the assume?
  209.         */
  210.     }
  211.  
  212.     if ( form == BASE ) {
  213.         if ( fixup->b_mode == mode && fixup->b_index == index ) {
  214.             return;
  215.         }
  216.     }
  217.  
  218.     this_name = mode_name( mode, index );
  219.     if ( this_name ) {
  220.         sprintf( result, "%s:", this_name );
  221.         return;
  222.     } else {
  223.         return;
  224.     }
  225. }
  226.  
  227. PUB_T *check_public( mode, index, displacement, label_char )
  228.     int             mode;
  229.     int             index;
  230.     long            displacement;
  231.     char            label_char;
  232. {
  233.     PUB_T           *new_pub_rec;
  234.     NODE_T          *new_node;
  235.     DAT_T           dat_search;
  236.     DAT_T           *dat_rec;
  237.     NODE_T          *dat_node;
  238.     FIX_T           *fix_rec;
  239.     NODE_T          *fix_node;
  240.     int             ref_seg;
  241.     char            label_name[10];
  242.     dword   disp;
  243.     int             fix_count;
  244.  
  245. #ifdef DEBUG
  246. printf("--> check_public for [%04X:%04lX]\n", index, displacement );
  247. #endif
  248.  
  249.     if ( over_seg == -1 ) {
  250.         ref_seg = 2;
  251.     } else {
  252.         ref_seg = over_seg;
  253.     }
  254.  
  255.     if ( displacement < 0L ) {
  256.         disp = 0L;
  257.     } else {
  258.         disp = displacement;
  259.     }
  260.  
  261.     if ( mode == 2 ) {
  262.         index = seg_rec->prv_index[ref_seg];
  263.     }
  264.  
  265.     pub_search.seg_idx = index;
  266.     pub_search.offset  = disp;
  267.  
  268.     new_pub_rec = (PUB_T *)find( (char *)&pub_search, public_tree,
  269.                                                     TC pub_compare, &new_node );
  270.     if ( new_pub_rec ) {
  271.         return( new_pub_rec );
  272.     }
  273.     /*
  274.     ** If the address is just slightly past another public symbol, and
  275.     ** the address is less than the public symbols address + its size,
  276.     ** then it is probably a "public+x" type fixup.
  277.     */
  278.     if ( new_node != public_tree ) {
  279.         new_pub_rec = (PUB_T *)new_node->data;
  280.         if ( new_pub_rec->seg_idx == index ) {
  281.             if ( new_pub_rec->offset + type_to_size(new_pub_rec->type) > disp ) {
  282.                 return( new_pub_rec );
  283.             }
  284.         }
  285.     }
  286.     /*
  287.     ** Find the data record that that symbol probably belongs in
  288.     */
  289.     dat_search.seg_idx = index;
  290.     dat_search.offset = disp;
  291.     dat_rec = (DAT_T *)find( (char *)&dat_search, data_tree, 
  292.                                                     TC dat_compare, &dat_node );
  293.     if ( dat_node && dat_node != data_tree ) {
  294.         dat_rec = (DAT_T *)dat_node->data;
  295.         if ( dat_rec->seg_idx == index 
  296.              && dat_rec->offset+dat_rec->length > disp ) {
  297.             /*
  298.             ** Make sure the symbol is not in the middle of a fixup
  299.             */
  300.             fix_search.seg_idx    = index;
  301.             fix_search.dat_offset = dat_rec->offset;
  302.             fix_search.offset     = (int)(disp - (dword)dat_rec->offset);
  303.             fix_rec = (FIX_T *)find( (char *)&fix_search, fix_tree,
  304.                                                       TC fix_compare, &fix_node );
  305.             if ( !fix_rec ) {
  306.                 if ( fix_node != fix_tree ) {
  307.                     fix_rec = (FIX_T *)fix_node->data;
  308.                     if ( fix_rec->seg_idx == index
  309.                          && fix_rec->dat_offset == dat_rec->offset ) {
  310.  
  311.                         fix_count = fix_type[fix_rec->form].num_bytes;
  312.  
  313.                         /*
  314.                         ** BASE types do not get larger
  315.                         */
  316.                         if ( fix_rec->extended && fix_rec->form != BASE ) {
  317.                             fix_count += 2;
  318.                         }
  319.                         if ( fix_search.offset > fix_rec->offset
  320.                           && fix_search.offset < fix_rec->offset+fix_count ) {
  321.                             return( new_pub_rec );
  322.                         }
  323.                     }
  324.                 }
  325.             }
  326.             /*
  327.             ** Make sure that public is not being placed inside an
  328.             ** iterated data block.  If it is, then retreat to the
  329.             ** start of the iterated data block.  In this way, labels
  330.             ** will never be generated inside iterated data blocks.
  331.             */
  332.             if ( dat_rec->type == ITERATED ) {
  333.                 if ( new_node == public_tree ) {
  334.                     return( NULL );
  335.                 }
  336.                 if ( new_pub_rec->seg_idx != index ) {
  337.                     return( NULL );
  338.                 }
  339.                 if ( new_pub_rec->offset >= dat_rec->offset ) {
  340.                     return( new_pub_rec );
  341.                 }
  342.                 disp = dat_rec->offset;
  343.             }
  344.         }
  345.     }
  346.  
  347.     /*
  348.     ** Create a local label (only happens on 1st pass!)
  349.     */
  350.     label_count++;
  351.     if ( compatibility == 2 ) {
  352.         sprintf( label_name, "@%c%d", label_char, label_count );
  353.     } else {
  354.         sprintf( label_name, "$%c%d", label_char, label_count );
  355.     }
  356. #ifdef DEBUG
  357. printf("Creating a new symbol <%s> at %d:%04X\n", label_name, index, disp);
  358. #endif
  359.  
  360.     new_node = pub_insert( index, disp, label_name, LOCAL, FALSE );
  361.  
  362.     new_pub_rec = (PUB_T *)find( (char *)&pub_search, public_tree,
  363.                                                         TC pub_compare, NULL );
  364.     if ( (pub_node == public_tree || index < pub_rec->seg_idx || 
  365.           (index == pub_rec->seg_idx && disp < pub_rec->offset)) &&
  366.            (index > segment || (index == segment && disp > inst_offset)) ) {
  367.         pub_node = new_node;
  368.         pub_rec  = new_pub_rec;
  369.     }
  370.     if ( index == segment && disp == inst_offset ) {
  371.         last_pub_rec = new_pub_rec;
  372.     }
  373.  
  374.     return( new_pub_rec );
  375. }
  376.  
  377. int find_member( text, structure, offset )
  378.     char    *text;
  379.     STRUC_T *structure;
  380.     long    *offset;
  381. {
  382.     int     type;
  383.     int     mem_cnt;
  384.     long    dup_cnt;
  385.     long     this_size;
  386.     char    *cp;
  387.     char    ch;
  388.  
  389.     mem_cnt = 0;
  390.     cp = structure->form;
  391.  
  392.     while ( (ch=*cp) != '\0' ) {
  393.         switch( ch ) {
  394.             case '(':
  395.                 dup_cnt = atol( cp+1 );
  396.                 break;
  397.             case ',':
  398.                 type = atoi( cp+1 );
  399.                 break;
  400.             case ')':
  401.                 this_size = type_to_size(type)*dup_cnt;
  402.                 if ( *offset < this_size ) {
  403.                     sprintf( text, ".s%dm_%d", structure->index, mem_cnt );
  404.                     return( type );
  405.                 }
  406.                 *offset -= this_size;
  407.                 mem_cnt++;
  408.             default:
  409.                 break;
  410.         }
  411.         cp++;
  412.     }
  413.  
  414.     strcpy( text, ".past struct" );
  415.  
  416.     return( UNKNOWN );
  417. }
  418.  
  419. void get_target( result, fixup, mode, data, pre_name, type, assign,
  420.                                                         type_known, seg_reg )
  421.     char        *result;        /* Output string                            */
  422.     FIX_T       *fixup;         /* Fixup to figure out                      */
  423.     int         mode;           /* 0 = Data Deref, 1 = Code, 2 = Data Ref   */
  424.     long        data;           /* Value added (fixups get added onto this) */
  425.     int         pre_name;       /* Are the fixup type words needed?         */
  426.     int         type;           /* type of value pointed to (word ptr, etc) */
  427.     int         assign;         /* Assign type if needed?                   */
  428.     int         *type_known;    /* Is the "word ptr" text needed? (result)  */
  429.     int         seg_reg;        /* Segment register used                    */
  430. {
  431.     int         index;
  432.     PUB_T       *pub_rec;
  433.     EXT_T       ext_search;
  434.     EXT_T       *ext_rec;
  435.     STRUC_T     *pub_struct;
  436.     char        *prefix;
  437.     char        this_seg[NAMESIZE+1+1];     /* 1 for ':', 1 for \0 */
  438.     char        this_member[NAMESIZE+1+1];  /* 1 for ., 1 for \0 */
  439.     word    seg_size;
  440.     char        *this_name;
  441.     char        *this_comment;
  442.     int         this_type;
  443.     char        sign;
  444.     long        disp;
  445.  
  446. #ifdef DEBUG
  447. printf("-> get_target for [%04X:%04X]\n", fix_rec->seg_idx, fix_rec->dat_offset );
  448. #endif
  449.  
  450.     disp = data;
  451.  
  452.     this_seg[0] = '\0';
  453.     this_member[0] = '\0';
  454.     this_comment = "";
  455.  
  456.     /*
  457.     ** Fixups cannot have a displacement value (stored with the fixup)
  458.     ** AND a value added (stored in the image to which the fixup is added)
  459.     */
  460.     if ( fixup->displacement != 0L ) {
  461.         if ( disp != 0L ) {
  462.             this_comment = "[MULTIPLE FIXUP]";
  463.         }
  464.         disp += fixup->displacement;
  465.     }
  466.  
  467.     if ( pre_name ) {
  468.         prefix = fix_type[fixup->form].prefix;
  469.     } else {
  470.         prefix = "";
  471.     }
  472.  
  473.     index = fixup->b_index;
  474.  
  475.     switch( fixup->b_mode ) {
  476.         case SEGMENT:           /* Segment Index and Displacement */
  477.             if ( fixup->form != BASE ) {
  478.                 /* PUBLIC names will be stored as segment + offset */
  479.                 pub_rec = check_public( 0, index, disp, 'S' );
  480.                 if ( pub_rec ) {
  481.                     this_name = pub_rec->name;
  482.                     disp -= (long)pub_rec->offset;
  483.                     pub_struct = pub_rec->structure;
  484.                     if ( pub_struct ) {
  485.                         this_type = find_member( this_member, pub_struct,
  486.                                                                       &disp );
  487.                     } else {
  488.                         if ( assign && ((type <= FAR && pub_rec->type > FAR)
  489.                                 || pub_rec->type == UNKNOWN) ) {
  490.                             pub_rec->type = type;
  491.                         }
  492.                         this_type = pub_rec->type;
  493.                     }
  494.                     if ( this_type != type ) {
  495.                         *type_known = FALSE;
  496.                     } else {
  497.                         *type_known = TRUE;
  498.                     }
  499.                     get_seg( this_seg, fixup, mode, pub_rec, seg_reg );
  500.                     break;
  501.                 }
  502.             }
  503.  
  504.             this_name = seg_name(index,&seg_size);
  505.             if ( fixup->form == BASE && fixup->displacement != 0 ) {
  506.                 prefix = "";        /* MASM generates seg length, if */
  507.                 disp -= seg_size;   /* "SEG" is missing, do the same */
  508.             }
  509.             this_seg[0] = '\0';
  510.             *type_known = TRUE;
  511.             break;
  512.         case GROUP:                     /* Group Index and Displacement */
  513.             this_name = grp_name(index);
  514.             *type_known = TRUE;
  515.             get_seg( this_seg, fixup, mode, NULL, seg_reg );
  516.             break;
  517.         case EXTERNAL:                  /* External Index and Displacement */
  518.             ext_search.index = index;
  519.             ext_rec = (EXT_T *)find( (char *)&ext_search,
  520.                                         extern_tree, TC ext_compare, NULL );
  521.             if ( ext_rec == NULL ) fmt_error( "Undefined external" );
  522.  
  523.             this_name = ext_rec->name;
  524.  
  525.             if ( assign && ((type <= FAR && ext_rec->type > FAR)
  526.                             || ext_rec->type == UNKNOWN) ) {
  527.                 ext_rec->type = type;
  528.             }
  529.             if ( ext_rec->type != type ) {
  530.                 *type_known = FALSE;
  531.             } else {
  532.                 *type_known = TRUE;
  533.             }
  534.             get_seg( this_seg, fixup, mode, ext_rec, seg_reg );
  535.             break;
  536.         case FRAME:                     /* Frame Number and Displacement */
  537.             get_seg( this_seg, fixup, mode, NULL, seg_reg );
  538.             break;
  539.     }
  540.  
  541.     if ( disp == 0 ) {
  542. /* ;* */ sprintf( result, "%s%s%s%s%s", prefix, this_seg,
  543.                      this_name, this_member, this_comment );
  544.     } else {
  545.         if ( disp > 0L ) {
  546.             sign = '+';
  547.         } else {
  548.             sign = '-';
  549.             disp = -disp;
  550.         }
  551.         if ( disp > 32767L || disp < -32768L ) {
  552.             sprintf( result, "%s%s%s%s %c 0%08lXh%s",
  553.                                 prefix, this_seg,
  554.                                 this_name, this_member,
  555.                                 sign, disp,
  556.                                 this_comment );
  557.         } else {
  558.             sprintf( result, "%s%s%s%s %c 0%04lXh%s",
  559.                                 prefix, this_seg,
  560.                                 this_name, this_member,
  561.                                 sign, disp,
  562.                                 this_comment );
  563.         }
  564.     }
  565. #ifdef DEBUG
  566. printf("<- get_target [%04X:%04X]\n", fix_rec->seg_idx, fix_rec->dat_offset );
  567. #endif
  568.  
  569. }
  570.  
  571. int get_fix( result, mode, pre_name, size_bytes, size, assign,
  572.                                                     size_known, seg_reg )
  573.     char            *result;        /* Resulting name will go here            */
  574.     int             mode;           /* 0 = Data Deref, 1 = Code, 2 = Data Ref */
  575.     int             pre_name;       /* Fixup type words needed?               */
  576.     int             size_bytes;     /* Word size (386=4 others=2)             */
  577.     int             size;           /* Size of expected value                 */
  578.     int             assign;         /* TRUE to set size, FALSE to ignore      */
  579.     int             *size_known;    /* Is "word ptr" text needed?             */
  580.     int             seg_reg;        /* Segment register used                  */
  581. {
  582.     dword   data;
  583.     dword   more;
  584.     int             fix_count;
  585.  
  586.     size_bytes = size_bytes;
  587.     fix_count = fix_type[fix_rec->form].num_bytes;
  588.  
  589.     /*
  590.     ** BASE types do not get larger
  591.     */
  592.     if ( fix_rec->extended && fix_rec->form != BASE ) {
  593.         fix_count += 2;
  594.     }
  595.  
  596.     switch( fix_count ) {
  597.         case 1: data = buff_getc();
  598.                 break;
  599.         case 2: data = buff_getc();
  600.                 data += (buff_getc() << 8);
  601.                 break;
  602.         case 4: data = buff_getc();
  603.                 data += (buff_getc() << 8);
  604.                 data += (buff_getc() << 16);
  605.                 data += (buff_getc() << 24);
  606.                 break;
  607.         case 6: data = buff_getc();
  608.                 data += (buff_getc() << 8);
  609.                 data += (buff_getc() << 16);
  610.                 data += (buff_getc() << 24);
  611.                 more = buff_getc();
  612.                 more += (buff_getc() << 8);
  613.                 break;
  614.         default:
  615.                 fmt_error( "Invalid fixup type" );
  616.                 break;
  617.     }
  618.  
  619.     get_target( result, fix_rec, mode, data, pre_name, size, assign,
  620.                                                         size_known, seg_reg );
  621.     fix_advance();
  622.  
  623.     return( fix_count );
  624. }
  625.